/*
 * Manager.cpp
 *
 *  Created on: 2011/06/23
 *      Author: naoki
 */

#include "StdAfx.h"
#include "Graphics/src/ManagerImpl.h"

namespace NTEngine {
namespace Graphics {

ManagerImpl* gManagerImpl = 0;

//const char ManagerImpl::sShaderSkinVertexLightingVsSrc[] = {
//#include "Graphics/src/shader/SkinVertexLightingVs.h"
//};

const char ManagerImpl::sShaderVertexLightingVsSrc[] = {
#include "Graphics/src/shader/VertexLightingVs.h"
};

const char ManagerImpl::sShaderBasicFsSrc[] = {
#include "Graphics/src/shader/BasicFs.h"
};

const char ManagerImpl::sShaderNoLightingVsSrc[] = {
#include "Graphics/src/shader/NoLightingVs.h"
};

const char ManagerImpl::sShaderPixelLightingVsSrc[] = {
#include "Graphics/src/shader/PixelLightingVs.h"
};

const char ManagerImpl::sShaderPixelLightingFsSrc[] = {
#include "Graphics/src/shader/PixelLightingFs.h"
};

namespace { // anonymous

// GLの場合はプリミティブの数ではなく頂点数なので計算で求める
// GLネイティブなタイプも取得する
// ここでしか使わないのでNULLチェックもしない
static void convertToGL( PrimitiveType t, int primitiveNumber, int* oNum, GLenum* oType ) {
	switch ( t ) {
	case PRIMITIVE_TRIANGLE:
		*oNum = primitiveNumber * 3;
		*oType = GL_TRIANGLES;
		break;
	case PRIMITIVE_TRIANGLE_STRIP:
		*oNum = primitiveNumber + 2;
		*oType = GL_TRIANGLE_STRIP;
		break;
	case PRIMITIVE_LINE:
		*oNum = primitiveNumber * 2;
		*oType = GL_LINES;
		break;
	case PRIMITIVE_POINT:
		*oNum = primitiveNumber;
		*oType = GL_POINTS;
		break;
	default:
		HALT( t );
	}
}

} // namespace {}

Manager::Manager() {
	ASSERT( Core::isMainThread() && "you must call from MAIN thread" );
}

Manager Manager::instance() {
	return Manager();
}

void Manager::enableDepthTest( bool f ) {
	gManagerImpl->enableDepthTest( f );
}

void Manager::enableDepthWrite( bool f ) {
	gManagerImpl->enableDepthWrite( f );
}

void Manager::setBlendMode( BlendMode b ) {
	gManagerImpl->setBlendMode( b );
}

void Manager::setCullMode( CullMode c ) {
	gManagerImpl->setCullMode( c );
}

void Manager::setTextureFilter( TextureFilter f ) {
	gManagerImpl->setTextureFilter( f );
}

void Manager::setVertexBuffer( VertexBuffer buffer ) {
	gManagerImpl->setVertexBuffer( buffer.mImpl );
}

void Manager::setIndexBuffer( IndexBuffer buffer ) {
	gManagerImpl->setIndexBuffer( buffer.mImpl );
}

void Manager::setTexture( Texture texture ) {
	gManagerImpl->setTexture( texture.mImpl );
}

void Manager::setProjectionViewMatrix( const Matrix4x4& m ) {
	gManagerImpl->setProjectionViewMatrix( m );
}

void Manager::setWorldMatrix( const Matrix3x4& m ) {
	gManagerImpl->setWorldMatrix( m );
}

void Manager::setViewport( int x, int y, int w, int h ) {
	gManagerImpl->setViewport( x, y, w, h );
}

void Manager::getViewport( int* x, int* y, int* w, int* h ) {
	gManagerImpl->getViewport( x, y, w, h );
}

void Manager::setLightingMode( LightingMode m ) {
	gManagerImpl->setLightingMode( m );
}

void Manager::setLightPosition( int idx, const Vector3& pos ) {
	gManagerImpl->setLightPosition( idx, pos );
}

void Manager::setLightIntensity( int idx, float intensity ) {
	gManagerImpl->setLightIntensity( idx, intensity );
}

void Manager::setLightColor( int idx, const Vector3& col ) {
	gManagerImpl->setLightColor( idx, col );
}

void Manager::setEyePosition( const Vector3& pos ) {
	gManagerImpl->setEyePosition( pos );
}

void Manager::setDiffuseColor( const Vector3& c ) {
	gManagerImpl->setDiffuseColor( c );
}

void Manager::setSpecularColor( const Vector3& c ) {
	gManagerImpl->setSpecularColor( c );
}

void Manager::setEmissionColor( const Vector3& c ) {
	gManagerImpl->setEmissionColor( c );
}

void Manager::setAmbientColor( const Vector3& c ) {
	gManagerImpl->setAmbientColor( c );
}

void Manager::setTransparency( float t ) {
	gManagerImpl->setTransparency( t );
}

void Manager::setSpecularSharpness( float e ) {
	gManagerImpl->setSpecularSharpness( e );
}

unsigned Manager::frameId() const {
	return gManagerImpl->mFrameId;
}

void Manager::draw( int offset, int primitiveNumber, PrimitiveType type ) {
	int vertexNumber;
	GLenum primitiveType;
	convertToGL( type, primitiveNumber, &vertexNumber, &primitiveType );
	gManagerImpl->draw( offset, vertexNumber, primitiveType );
}

void Manager::drawIndexed( int offset, int primitiveNumber, PrimitiveType type ) {
	int vertexNumber;
	GLenum primitiveType;
	convertToGL( type, primitiveNumber, &vertexNumber, &primitiveType );
	gManagerImpl->drawIndexed( offset, vertexNumber, primitiveType );
}

int Manager::width() const {
	return gManagerImpl->mWidth;
}

int Manager::height() const {
	return gManagerImpl->mHeight;
}

int Manager::fullScreenWindowWidth() const {
	return gManagerImpl->mWidth;
}

int Manager::fullScreenWindowHeight() const {
	return gManagerImpl->mHeight;
}

void Manager::create(
	void* p,
	int width, int height, // バックバッファ幅、高さ
	bool enableDepthStencil, // 深度バッファ
	bool enableAntialias, // マルチサンプリングアンチエイリアス
	bool enableAnisotropicFilter, // 異方性フィルタ
	bool translucent, // レンダーサーフェースを半透明で使うか
	bool , // 垂直同期
	bool  // ウィンドウモード
) {
	HARD_ASSERT( gManagerImpl == NULL );
	gManagerImpl = NEW ManagerImpl(
		static_cast< android_app* >( p ),
		enableDepthStencil,
		enableAntialias,
		enableAnisotropicFilter,
		translucent
	);
}

void Manager::destroy() {
	SAFE_DELETE( gManagerImpl );
}

void Manager::restore() {
	gManagerImpl->restore();
}

void Manager::release() {
	gManagerImpl->release();
}

void Manager::changeDisplayMode( bool ) {
	gManagerImpl->changeDisplayMode();
}

void Manager::beginRender() {
	gManagerImpl->beginRender();
}

void Manager::endRender() {
	gManagerImpl->endRender();
}

bool Manager::canRender() const {
	return gManagerImpl->canRender();
}

} // namespace Graphics
} // namespace NtEngine
